package com.demo.coroutinedemo1

import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.supervisorScope
import  org.junit.Test
import kotlin.system.measureTimeMillis

/**
 * Created by zhangyuncai on 2025/1/18.
 * 描述：
 */
class CoroutineTest01 {
    @Test
    fun `test coroutine builder`() {
        GlobalScope.launch {

        }
    }

    /*
    runBlocking包装主协程,会执行所有子协程
     */
    @Test
    fun `test coroutine builder2`() = runBlocking {
        val job1 = launch {//不返回任何结果值
            delay(200)
            println("job1 finished")
        }

        val job2 = async {//返回任何结果值
            delay(200)
            println("job2 finished")
            "job2 result"
        }
        println("job2.await()=${job2.await()}")
    }

    @Test
    fun `test coroutine join`() = runBlocking {
        val job1 = launch {
            delay(5000)
            println("one")
        }
        job1.join()//这行代码表示从上至下按序执行,也就是这行job1完了之后再往下执行
        val job2 = launch {
            delay(3000)
            println("two")
        }
        val job3 = launch {
            delay(200)
            println("three")
        }
        val job4 = launch {
            delay(2000)
            println("four")
        }
    }

    @Test
    fun `test coro utine await`() = runBlocking {
        val job1 = async {
            delay(2000)
            println("one")
        }
        job1.await()//这行代码表示从上至下按序执行
        val job2 = async {
            delay(200)
            println("two")
        }
        val job3 = async {
            delay(200)
            println("three")
        }
    }

    @Test
    fun `test sync`() = runBlocking {
        val time=measureTimeMillis {//可以测出时长
            val one = doOne()
            val two = doTwo()
            println("result:${one + two}")
        }
        println("time:${time}")
    }

    @Test
    fun `test combine async`() = runBlocking {
        val time=measureTimeMillis {
            val one = async { doOne() }
//            val one = async { doOne() }.await()//这么写是有区别的，如果这么写表示按序执行
            val two = async { doTwo() }
            println("result:${one.await() + two.await()}")//如果这么写表示两者同时执行
        }
        println("time:${time}")
    }

    private suspend fun doOne(): Int {
        delay(1000)
        return 14
    }

    private suspend fun doTwo(): Int {
        delay(1000)
        return 25
    }

    @Test
    fun`test start mode`(): Unit = runBlocking {
        /*
        DEFAULT协程创建后，立即开始调度，在调度前如果协程被取消，其将直接进入取消
响应的状态
ATOMIC:协程创建后，立即开始调度，协程执行到第一个挂起点之前不响应取消。
>LAZY:只有协程被需要时，包括主动调用协程的start、join或者await等函数时才会开始
调度，如果调度前就被取消，那么该协程将直接进入异常结束状态。
>UNDISPATCHED:协程创建后立即在当前函数调用栈中执行，直到遇到第一个真正挂起
的点。
         */
//        val job=launch(start = CoroutineStart.DEFAULT) {
//            delay(10000)
//            println("job finished")
//        }
//        delay(1000)
//        job.cancel()
//        val job=launch(start = CoroutineStart.ATOMIC) {
//            println("job start")
//            delay(5000)//在这之前不能被取消
//            println("job finished1")
//            delay(10000)
//            println("job finished2")
//        }
//        delay(1000)
//        job.cancel()
//        val job=async(start = CoroutineStart.LAZY) {
//            println("job start")
//            delay(3000)//在这之前不能被取消
//            println("job finished1")
//            delay(5000)
//            println("job finished2")
//            return@async 12
//        }
//        job.start()
//        delay(1000)
//        job.cancel()

        val job=async(context = Dispatchers.IO, start = CoroutineStart.UNDISPATCHED){
            println("thread:${Thread.currentThread().name}")
        }
    }

    /*
    runBlocking是常规函数
    coroutineScope是挂起函数,等待所有子协程执行完毕,只要有一个子协程挂了,所有子协程全部挂了
     */
    @Test
    fun `test coroutine scope builder`()= runBlocking {
        coroutineScope {
            val job1=launch {
                delay(400)
                println("job1 finished")
            }
            val job2=async {
                delay(200)
                println("job2 finished")
                "job2 result"
                throw Exception("失败了")
            }
        }
    }

    /*
    supervisorScope,一个子协程崩溃,不会影响其他子协程
     */
    @Test
    fun `test supervisor scope builder`()= runBlocking {
        supervisorScope {
            val job1=launch {
                delay(400)
                println("job1 finished")
            }
            val job2=async {
                delay(200)
                println("job2 finished")
                "job2 result"
                throw Exception("失败了")
            }
        }
    }
}